#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Net;
using GrapplingHookGameData;

#endregion

namespace GrapplingHookGame
{
    /// <summary>
    /// This screen implements the actual game logic. It is just a
    /// placeholder to get the idea across: you'll probably want to
    /// put some more interesting gameplay in here!
    /// </summary>
    class GameplayScreen : GameScreen
    {
        #region Fields
        private Camera2D camera;
        private SpriteFont gameFont;
        private string levelName;
        private int rounds;
        private NetworkSession networkSession;
        private List<HealthBar> localPlayerHealthBars;
        #endregion

        #region Properties


        /// <summary>
        /// The logic for deciding whether the game is paused depends on whether
        /// this is a networked or single player game. If we are in a network session,
        /// we should go on updating the game even when the user tabs away from us or
        /// brings up the pause menu, because even though the local player is not
        /// responding to input, other remote players may not be paused. In single
        /// player modes, however, we want everything to pause if the game loses focus.
        /// </summary>
        new bool IsActive
        {
            get
            {
                if (networkSession == null)
                {
                    // Pause behavior for single player games.
                    return base.IsActive;
                }
                else
                {
                    // Pause behavior for networked games.
                    return !IsExiting;
                }
            }
        }


        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public GameplayScreen(NetworkSession networkSession, string levelName, int rounds)
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
            this.networkSession = networkSession;
            this.levelName = levelName;
            this.rounds = rounds;
            localPlayerHealthBars = new List<HealthBar>();
            
        }


        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void LoadContent()
        {
            GameSession.StartNewSession(ScreenManager, this, networkSession, levelName, rounds);
            gameFont = GameSession.ContentManager.Load<SpriteFont>("gamefont");

            //load health bars
            int x = 200;
            foreach (LocalNetworkGamer localGamer in networkSession.LocalGamers)
            {
                Player p = localGamer.Tag as Player;
                HealthBar h = new HealthBar(new Vector2(x, 50), p );
                h.LoadContent(GameSession.ContentManager);
                localPlayerHealthBars.Add(h);
                x += (int)h.Width+100;
            }

            //create camera
            camera = new Camera2D(ScreenManager.Game, false);
            camera.Origin = new Vector2(ScreenManager.GraphicsDevice.Viewport.Width / 2, ScreenManager.GraphicsDevice.Viewport.Height / 2);
            ScreenManager.Game.Components.Add(camera);
        }

        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        public override void UnloadContent()
        {
        }


        #endregion

        #region Update


        /// <summary>
        /// Updates the state of the game.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);

            if (IsActive)
            {
                //update game elements based on if this is the server or client
                GameSession.Update(gameTime);

                //move camera to players
                List<Vector2> positions = new List<Vector2>(networkSession.LocalGamers.Count);
                foreach (LocalNetworkGamer gamer in networkSession.LocalGamers)
                {
                    positions.Add(((Player)gamer.Tag).Position);

                }
                camera.MoveAndZoomToIncludeLocations(positions);
                camera.EnsureIsWithinRectangle(new Rectangle(-Constants.TILE_WIDTH / 2, -Constants.TILE_HEIGHT / 2, GameSession.CurrentLevel.LevelDefinition.Width * Constants.TILE_WIDTH, GameSession.CurrentLevel.LevelDefinition.Height * Constants.TILE_HEIGHT));

                //update health display
                foreach(HealthBar h in localPlayerHealthBars )
                {
                    h.Update(gameTime, networkSession.IsHost);
                }
            }
            // If we are in a network game, check if we should return to the lobby.
            if ((networkSession != null) && !IsExiting)
            {
                if (networkSession.SessionState == NetworkSessionState.Lobby)
                {
                    LoadingScreen.Load(ScreenManager, true,
                                       new BackgroundScreen(),
                                       new LobbyScreen(networkSession));
                }
            }

        }


        /// <summary>
        /// Lets the game respond to player input. Unlike the Update method,
        /// this will only be called when the gameplay screen is active.
        /// </summary>
        public override void HandleInput(InputState input)
        {
            if (input.PauseGame)
            {
                // If they pressed pause, bring up the pause menu screen.
                ScreenManager.AddScreen(new PauseMenuScreen(networkSession));
            }
            else
            {
                GameSession.HandleInput(input);
            }
        }


        #endregion

        #region Draw

        /// <summary>
        /// Draws the gameplay screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            ScreenManager.GraphicsDevice.Clear(ClearOptions.Target, Color.Black, 0, 0);

            ScreenManager.SpriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None, camera.Transform);
            
            //draw game
            GameSession.Draw(gameTime);

            ScreenManager.SpriteBatch.End();

            //draw health bars
            ScreenManager.SpriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);
            foreach (HealthBar h in localPlayerHealthBars)
            {
                h.Draw(ScreenManager.SpriteBatch);
            }
            ScreenManager.SpriteBatch.End();

            //draw particles. They have their own begin/end on spritebatch because they need to use additive blend mode
            GameSession.ExplosionParticleSystem.Draw(ScreenManager.SpriteBatch, camera.Transform);

            // If the game is transitioning on or off, fade it out to black.
            if (TransitionPosition > 0)
                ScreenManager.FadeBackBufferToBlack(255 - TransitionAlpha);
        }


        #endregion
    }
}
